use config::Config;
use std::collections::HashMap;
use std::error::Error;
use std::fs;

pub const CONFIG_FILE_NAME: &str = "./config.yaml";

pub struct AppLauncherUpdaterConfig {
    run_exec_command: String,          // 启动时执行命令的地址
    server_path: String,               // 更新地址 HTTP://
    validate_exec_command: String,     // 用于测试新jar包是否能执行的验证命令
    validate_exec_response: String,    // 测试命令执行完毕应该响应的标准输出流内容(支持正则)
    launcher_file_name: String,        // 启动器当前版本名字
    launcher_update_file_name: String, // 下载更新的名字
    launcher_backup_file_name: String, // 备份版本的启动器名字
}

impl AppLauncherUpdaterConfig {
    pub fn load() -> Result<AppLauncherUpdaterConfig, Box<dyn Error>> {
        match fs::exists(CONFIG_FILE_NAME) {
            Ok(exists) => {
                if !exists {
                    Err("配置文件不存在")?
                }
            }
            Err(e) => Err(e)?,
        };

        let settings = Config::builder()
            .add_source(config::File::with_name(CONFIG_FILE_NAME))
            .build()
            .unwrap();

        let config_map = settings
            .try_deserialize::<HashMap<String, String>>()
            .unwrap();

        let run_exec_command = extract_field(&config_map, "run_exec")?;
        let server_path = extract_field(&config_map, "server_path")?;
        let validate_exec_command = extract_field(&config_map, "validate_exec_command")?;
        let validate_exec_response = extract_field(&config_map, "validate_exec_response")?;
        let launcher_file_name = extract_field(&config_map, "launcher_file_name")?;
        let launcher_update_file_name = extract_field(&config_map, "launcher_update_file_name")?;
        let launcher_backup_file_name = extract_field(&config_map, "launcher_backup_file_name")?;

        Ok(AppLauncherUpdaterConfig {
            run_exec_command,
            server_path,
            validate_exec_command,
            validate_exec_response,
            launcher_file_name,
            launcher_update_file_name,
            launcher_backup_file_name,
        })
    }

    pub fn run_exec_command(&self) -> &str {
        &self.run_exec_command
    }

    pub fn server_path(&self) -> &str {
        &self.server_path
    }

    pub fn validate_exec_command(&self) -> &str {
        &self.validate_exec_command
    }

    pub fn validate_exec_response(&self) -> &str {
        &self.validate_exec_response
    }

    pub fn launcher_file_name(&self) -> &str {
        &self.launcher_file_name
    }

    pub fn launcher_update_file_name(&self) -> &str {
        &self.launcher_update_file_name
    }

    pub fn launcher_backup_file_name(&self) -> &str {
        &self.launcher_backup_file_name
    }
}

fn extract_field(
    map: &HashMap<String, String>,
    key: &'static str,
) -> Result<String, Box<dyn Error>> {
    map.get(key)
        .map(|s| s.to_string())
        .ok_or_else(|| format!("Missing config field: {}", key).into())
}
